﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YJKFamilyLibDataManager
{
	internal class SqliteTypeTable : ITypeTable
	{
		public SqliteTypeTable(FamilyLibDatabase db)
		{
			this.mDatabase = db;
		}

		public bool Add(DataTable typeTable, DbFamily family, DbTransaction tr)
		{
			if (typeTable.Columns.Contains("TypeId"))
			{
				typeTable.Columns.Remove("TypeId");
			}
			string str = string.Concat(new string[]
			{
				"insert into [",
				family.Guid.ToString(),
				"]([",
				typeTable.Columns[0].ColumnName,
				"]"
			});
			for (int i = 1; i < typeTable.Columns.Count; i++)
			{
				str = str + ",[" + typeTable.Columns[i].ColumnName + "]";
			}
			str += ") values (";
			for (int j = 0; j < typeTable.Rows.Count; j++)
			{
				if (typeTable.Rows[j]["规格名"].ToString().Trim() == "")
				{
					MessageBox.Show(family.Name + "族，第" + (j + 1).ToString() + "条记录规格名为空,添加失败。", "族库管理");
				}
				else
				{
					string text = str + "'" + typeTable.Rows[j][0].ToString() + "'";
					for (int k = 1; k < typeTable.Columns.Count; k++)
					{
						text = text + ",'" + typeTable.Rows[j][k].ToString() + "'";
					}
					text += ")";
					try
					{
						this.mDatabase.ExecuteCommand(text, tr);
					}
					catch
					{
						MessageBox.Show(family.Name + "族，第" + (j + 1).ToString() + "条记录添加失败，请检查规格名是否重名。", "族库管理");
					}
				}
			}
			typeTable.Rows.Clear();
			return true;
		}

		public void Update(DataTable typeTable, DbFamily family)
		{
			for (int i = 0; i < typeTable.Rows.Count; i++)
			{
				if (typeTable.Rows[i]["规格名"].ToString().Trim() == "")
				{
					MessageBox.Show("第" + (i + 1).ToString() + "条记录规格名为空,更新失败。", "族库管理");
				}
				else
				{
					string text = string.Format("UPDATE [{0}] SET [{1}]='{2}'", family.Guid.ToString(), typeTable.Columns[0].ColumnName, typeTable.Rows[i][0]);
					for (int j = 1; j < typeTable.Columns.Count; j++)
					{
						text += string.Format(",[{0}]='{1}'", typeTable.Columns[j].ColumnName, typeTable.Rows[i][j]);
					}
					text += string.Format(" WHERE [TypeId]='{0}'", typeTable.Rows[i]["TypeId"]);
					if (!this.mDatabase.ExecuteCommand(text))
					{
						MessageBox.Show("第" + i.ToString() + "条记录修改失败");
					}
				}
			}
		}

		public DbFamilySymbol this[DbFamily family, string name]
		{
			get
			{
				DbFamilySymbol dbFamilySymbol = new DbFamilySymbol(family, name);
				dbFamilySymbol.SetDatabase(this.mDatabase);
				DataTable dataTable = this.mDatabase.ExecQuery(string.Concat(new string[]
				{
					"select * from [",
					family.Guid.ToString(),
					"] where [规格名]=\"",
					name.Trim(),
					"\""
				}));
				if (dataTable != null && dataTable.Rows.Count > 0)
				{
					dataTable.Columns.Remove("规格名");
					dataTable.Columns.Remove("TypeId");
					IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
					for (int i = 0; i < dataTable.Columns.Count; i++)
					{
						string columnName = dataTable.Columns[i].ColumnName;
						DbParamDefinition dbParamDefinition = familyParamTable[family, columnName];
						if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType != ParamDefinitionType.InstanceParam)
						{
							DbParameter item = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
							dbFamilySymbol.Params.Add(item);
						}
					}
				}
				return dbFamilySymbol;
			}
		}

		DataTable ITypeTable.SelectTypes(string SQL)
		{
			throw new NotImplementedException();
		}

		public void AddColumns(DbFamily family, List<DbParamDefinition> paramDefs, DbTransaction tr)
		{
			for (int i = 0; i < paramDefs.Count; i++)
			{
				if (paramDefs[i].ParamDefinitionType != ParamDefinitionType.InstanceParam)
				{
					try
					{
						string typeStringFromStorageType = this.getTypeStringFromStorageType(paramDefs[i].StorageType);
						this.mDatabase.ExecuteCommand(string.Concat(new string[]
						{
							"alter table [",
							family.Guid.ToString(),
							"] add [",
							paramDefs[i].Name,
							"] ",
							typeStringFromStorageType
						}), tr);
					}
					catch
					{
					}
				}
			}
		}

		private string getTypeStringFromStorageType(StorageType storageType)
		{
			string result = "CHAR";
            if (storageType == null || (int)storageType == 3 || (int)storageType == 4)
			{
				result = "CHAR";
			}
            else if ((int)storageType == 1)
			{
				result = "INT";
			}
            else if ((int)storageType == 2)
			{
				result = "DOUBLE";
			}
			return result;
		}

		private string getTypeStringFromType(Type type)
		{
			string result = "CHAR";
			if (type == typeof(string))
			{
				result = "CHAR";
			}
			else if (type == typeof(int) || type == typeof(long))
			{
				result = "INT";
			}
			else if (type == typeof(double))
			{
				result = "DOUBLE";
			}
			else if (type == null)
			{
				result = "DBNull";
			}
			return result;
		}

		public bool Create(DbFamily family, DbTransaction tr)
		{
			bool result;
			try
			{
				string text = string.Format("create table [{0}] ([TypeId] INTEGER PRIMARY KEY AUTOINCREMENT,[规格名] CHAR NOT NULL", family.Guid.ToString());
				for (int i = 0; i < family.ParamDefinitionList.Count; i++)
				{
					string typeStringFromStorageType = this.getTypeStringFromStorageType(family.ParamDefinitionList[i].StorageType);
					if (family.ParamDefinitionList[i].ParamDefinitionType == ParamDefinitionType.CustomParam || family.ParamDefinitionList[i].ParamDefinitionType == ParamDefinitionType.TypeParam)
					{
						text += string.Format(",[{0}] {1}", family.ParamDefinitionList[i].Name.Trim(), typeStringFromStorageType);
					}
				}
				text += ",constraint uk_name unique ([规格名]));";
				if (this.mDatabase.ExecuteCommand(text, tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public bool Create(DbFamily family, DataTable dt, DbTransaction tr)
		{
			bool result;
			try
			{
				string text = string.Format("create table [{0}] ([{1}] integer PRIMARY KEY autoincrement", family.Guid.ToString(), dt.Columns[0].ColumnName.Trim());
				for (int i = 1; i < dt.Columns.Count; i++)
				{
					string typeStringFromType = this.getTypeStringFromType(dt.Columns[i].DataType);
					text += string.Format(",[{0}] {1}", dt.Columns[i].ColumnName.Trim(), typeStringFromType);
				}
				text += ",constraint uk_name unique ([规格名]));";
				if (this.mDatabase.ExecuteCommand(text, tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public bool Drop(DbFamily family, DbTransaction tr)
		{
			bool result;
			try
			{
				if (this.mDatabase.ExecuteCommand("drop table [" + family.Guid.ToString() + "]", tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public DataTable DataTable(DbFamily family)
		{
			SqliteFamilyParamTable sqliteFamilyParamTable = new SqliteFamilyParamTable(this.mDatabase);
			List<DbParamDefinition> list = sqliteFamilyParamTable[family];
			list.Sort(new ParamDefinitionComp());
			string text = "[TypeId],[规格名]";
			for (int i = 0; i < list.Count; i++)
			{
				DbParamDefinition dbParamDefinition = list[i];
				if (dbParamDefinition.ParamDefinitionType != ParamDefinitionType.InstanceParam)
				{
					text = text + ",[" + list[i].Name + "]";
				}
			}
			return this.mDatabase.ExecQuery(string.Concat(new string[]
			{
				"select ",
				text,
				" from [",
				family.Guid.ToString(),
				"]"
			}));
		}

		public List<string> this[DbFamily family]
		{
			get
			{
				List<string> list = new List<string>();
				DataTable dataTable = this.DataTable(family);
				if (dataTable != null)
				{
					for (int i = 0; i < dataTable.Rows.Count; i++)
					{
						list.Add(dataTable.Rows[i]["规格名"].ToString());
					}
				}
				return list;
			}
		}

		public bool Remove(int typeId, DbFamily family)
		{
			string commandStr = string.Concat(new object[]
			{
				"delete from [",
				family.Guid.ToString(),
				"] where [TypeId]='",
				typeId,
				"'"
			});
			return this.mDatabase.ExecuteCommand(commandStr);
		}

		private FamilySymbol FindSymbol(Family family, string symbolName)
		{
			FamilySymbol result = null;
			List<FamilySymbol> symbols = family.GetSymbols();
			foreach (FamilySymbol familySymbol in symbols)
			{
				if (familySymbol.Name == symbolName || familySymbol.Name == symbolName.ToUpper() || familySymbol.Name == symbolName.ToLower())
				{
					result = familySymbol;
					break;
				}
			}
			return result;
		}

		public FamilySymbol CreateFamilySymbol(DbFamily dbFamily, string name, Document doc)
		{
			bool flag = false;
			Document document = null;
			Watch watch = new Watch();
			watch.Start("查找或加载族");
			Family family = dbFamily.Load(doc);
			watch.Stop();
			watch.Start("查找规格");
			FamilySymbol familySymbol = this.FindSymbol(family, name);
			watch.Stop();
			if (familySymbol == null)
			{
				watch.Start("创建规格");
				this.CreateNewType(dbFamily, name, doc, ref flag, ref document, family);
				watch.Stop();
			}
			else
			{
				watch.Start("对比创建GUID及已有参数");
				this.UpdateType(dbFamily, name, doc, ref flag, ref document, family, familySymbol);
				watch.Stop();
			}
			if (flag)
			{
				watch.Start("重新加载族");
				family = document.LoadFamily(doc, new FamilyOptions());
				familySymbol = this.FindSymbol(family, name);
				watch.Stop();
			}
			if (document != null)
			{
				document.Close(false);
				document.Dispose();
			}
			return familySymbol;
		}

		private void UpdateType(DbFamily dbFamily, string name, Document doc, ref bool reLoad, ref Document familyDoc, Family family, FamilySymbol fs)
		{
			Parameter parameter = fs.GetParameter("GUID");
			if (parameter == null || parameter.AsString() == "")
			{
				if (familyDoc == null)
				{
					familyDoc = doc.EditFamily(family);
				}
				FamilyManager familyManager = familyDoc.FamilyManager;
				Transaction transaction = new Transaction(familyDoc, "CreateGUID");
				transaction.Start();
				try
				{
					if (familyDoc.IsFamilyDocument)
					{
						reLoad = true;
						foreach (object obj in familyManager.Types)
						{
							FamilyType familyType = (FamilyType)obj;
							if (familyType.Name == fs.Name)
							{
								familyManager.CurrentType = familyType;
								break;
							}
						}
						if (familyManager.get_Parameter("GUID") == null)
						{
                            FamilyParameter familyParameter = familyManager.AddParameter("GUID", BuiltInParameterGroup.PG_TEXT, (ParameterType)1, false);
							familyManager.Set(familyParameter, dbFamily.Guid.ToString());
							transaction.Commit();
						}
					}
				}
				catch
				{
					transaction.RollBack();
				}
			}
			DataTable dataTable = this.mDatabase.ExecQuery(string.Concat(new string[]
			{
				"select * from [",
				dbFamily.Guid.ToString(),
				"] where [规格名]=\"",
				name.Trim(),
				"\""
			}));
			if (dataTable != null && dataTable.Rows.Count > 0)
			{
				dataTable.Columns.Remove("规格名");
				dataTable.Columns.Remove("TypeId");
				IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
				for (int i = 0; i < dataTable.Columns.Count; i++)
				{
					string columnName = dataTable.Columns[i].ColumnName;
					DbParamDefinition dbParamDefinition = familyParamTable[dbFamily, columnName];
					if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam && dataTable.Rows[0][i] != null && Convert.ToString(dataTable.Rows[0][i]) != "")
					{
						DbParameter dbParameter = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
						if (dbParameter.ParamDefinition.ParamDefinitionType != ParamDefinitionType.TypeParam && dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam && fs.GetParameter(dbParameter.ParamDefinition.Name) == null)
						{
							if (familyDoc == null)
							{
								familyDoc = doc.EditFamily(family);
							}
							FamilyManager familyManager2 = familyDoc.FamilyManager;
							Transaction transaction2 = new Transaction(familyDoc, "CreateCustomParam");
							transaction2.Start();
							try
							{
								reLoad = true;
                                FamilyParameter familyParameter2 = familyManager2.AddParameter(dbParameter.ParamDefinition.Name, BuiltInParameterGroup.PG_TEXT, (ParameterType)1, false);
                                switch ((int)familyParameter2.StorageType)
								{
								case 1:
									familyManager2.Set(familyParameter2, Convert.ToInt32(dbParameter.Value));
									break;
								case 2:
									familyManager2.Set(familyParameter2, AssistFunc.mmToFeet(Convert.ToDouble(dbParameter.Value)));
									break;
								case 3:
									familyManager2.Set(familyParameter2, Convert.ToString(dbParameter.Value));
									break;
								case 4:
								{
									object value = dbParameter.Value;
									break;
								}
								}
								transaction2.Commit();
							}
							catch
							{
								transaction2.RollBack();
							}
						}
					}
				}
			}
		}

		private void CreateNewType(DbFamily dbFamily, string name, Document doc, ref bool reLoad, ref Document familyDoc, Family family)
		{
			familyDoc = doc.EditFamily(family);
			if (familyDoc != null && familyDoc.IsFamilyDocument)
			{
				FamilyManager familyManager = familyDoc.FamilyManager;
				Transaction transaction = new Transaction(familyDoc, "CreateTypeTransaction");
				transaction.Start();
				try
				{
					SubTransaction subTransaction = new SubTransaction(familyDoc);
					subTransaction.Start();
					try
					{
						if (familyManager.get_Parameter("GUID") == null)
						{
							reLoad = true;
                            FamilyParameter familyParameter = familyManager.AddParameter("GUID", BuiltInParameterGroup.PG_TEXT, (ParameterType)1, false);
							familyManager.Set(familyParameter, dbFamily.Guid.ToString());
						}
						subTransaction.Commit();
					}
					catch
					{
						subTransaction.RollBack();
					}
					familyManager.NewType(name);
					DataTable dataTable = this.mDatabase.ExecQuery(string.Concat(new string[]
					{
						"select * from [",
						dbFamily.Guid.ToString(),
						"] where [规格名]=\"",
						name.Trim(),
						"\""
					}));
					if (dataTable != null && dataTable.Rows.Count > 0)
					{
						dataTable.Columns.Remove("规格名");
						dataTable.Columns.Remove("TypeId");
						IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
						for (int i = 0; i < dataTable.Columns.Count; i++)
						{
							string columnName = dataTable.Columns[i].ColumnName;
							DbParamDefinition dbParamDefinition = familyParamTable[dbFamily, columnName];
							if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType != ParamDefinitionType.InstanceParam && dataTable.Rows[0][i] != null && Convert.ToString(dataTable.Rows[0][i]) != "")
							{
								DbParameter dbParameter = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
								if (dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.TypeParam)
								{
									SubTransaction subTransaction2 = new SubTransaction(familyDoc);
									subTransaction2.Start();
									try
									{
										FamilyParameter familyParameter2 = familyManager.get_Parameter(dbParameter.ParamDefinition.Name);
										if (familyParameter2 != null && !familyParameter2.IsReadOnly)
										{
                                            switch ((int)familyParameter2.StorageType)
											{
											case 1:
												familyManager.Set(familyParameter2, Convert.ToInt32(dbParameter.Value));
												break;
											case 2:
												familyManager.Set(familyParameter2, Convert.ToDouble(dbParameter.Value) / Convert.ToDouble(UnitConvertC.ImperialDutRatio(dbParameter.ParamDefinition.DisplayUnitType)));
												break;
											case 3:
												familyManager.Set(familyParameter2, Convert.ToString(dbParameter.Value));
												break;
											case 4:
											{
												object value = dbParameter.Value;
												break;
											}
											}
										}
										subTransaction2.Commit();
										goto IL_3AC;
									}
									catch
									{
										subTransaction2.RollBack();
										goto IL_3AC;
									}
								}
								if (dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam)
								{
									SubTransaction subTransaction3 = new SubTransaction(familyDoc);
									subTransaction3.Start();
									try
									{
                                        FamilyParameter familyParameter3 = familyManager.AddParameter(dbParameter.ParamDefinition.Name, BuiltInParameterGroup.PG_TEXT, (ParameterType)1, false);
										if (familyParameter3 != null && !familyParameter3.IsReadOnly)
										{
                                            switch ((int)familyParameter3.StorageType)
											{
											case 1:
												familyManager.Set(familyParameter3, Convert.ToInt32(dbParameter.Value));
												break;
											case 2:
												familyManager.Set(familyParameter3, AssistFunc.mmToFeet(Convert.ToDouble(dbParameter.Value)));
												break;
											case 3:
												familyManager.Set(familyParameter3, Convert.ToString(dbParameter.Value));
												break;
											case 4:
											{
												object value2 = dbParameter.Value;
												break;
											}
											}
										}
										subTransaction3.Commit();
									}
									catch
									{
										subTransaction3.RollBack();
									}
								}
							}
							IL_3AC:;
						}
					}
					transaction.Commit();
				}
				catch (Exception ex)
				{
					transaction.RollBack();
					throw ex;
				}
				finally
				{
					transaction.Dispose();
				}
			}
		}

		public FamilySymbol CreateFamilySymbol(DbFamily dbFamily, string name, Document doc, ref int host)
		{
			Family family = dbFamily.Load(doc);
			Parameter parameter = family.get_Parameter(BuiltInParameter.FAMILY_HOSTING_BEHAVIOR);
			if (parameter != null)
			{
				host = parameter.AsInteger();
			}
			bool flag = false;
			Document document = null;
			FamilySymbol familySymbol = this.FindSymbol(family, name);
			if (familySymbol == null)
			{
				this.CreateNewType(dbFamily, name, doc, ref flag, ref document, family);
			}
			else
			{
				this.UpdateType(dbFamily, name, doc, ref flag, ref document, family, familySymbol);
			}
			if (flag)
			{
				family = document.LoadFamily(doc, new FamilyOptions());
				familySymbol = this.FindSymbol(family, name);
			}
			if (document != null)
			{
				document.Close(false);
				document.Dispose();
			}
			return familySymbol;
		}

		private bool CompareParameter(Parameter param, DbParameter dbParam)
		{
			bool result = false;
            switch ((int)param.StorageType)
			{
			case 0:
				result = true;
				break;
			case 1:
			{
				int num = param.AsInteger();
				int num2 = Convert.ToInt32(dbParam.Value);
				if (num == num2)
				{
					result = true;
				}
				break;
			}
			case 2:
			{
				double num3 = param.AsDouble();
				double num4 = AssistFunc.mmToFeet(Convert.ToDouble(dbParam.Value));
				if (num3 == num4)
				{
					result = true;
				}
				break;
			}
			case 3:
			{
				string a = param.AsString();
				string a2 = param.AsValueString();
				string b = Convert.ToString(dbParam.Value);
				if (a == b || a2 == b)
				{
					result = true;
				}
				break;
			}
			case 4:
			{
				int integerValue = param.AsElementId().IntegerValue;
				int num5 = Convert.ToInt32(dbParam.Value);
				if (integerValue == num5)
				{
					result = true;
				}
				break;
			}
			}
			return result;
		}

		private FamilyLibDatabase mDatabase;
	}
}
